package com.zijidelu.luframework.starter.scanner.impl;

import com.zijidelu.luframework.utils.cache.vault.Vault;
import com.zijidelu.luframework.utils.collection.stream.StreamUtil;
import com.zijidelu.luframework.utils.spring.beans.generic.SpringBeanTypeUtil;
import com.zijidelu.luframework.constant.RepositoryConstant;
import com.zijidelu.luframework.domain.repository.AggregateRepository;
import com.zijidelu.luframework.infrastructure.converter.AggregateRootConverter;
import com.zijidelu.luframework.infrastructure.persistence.repository.core.domain.AbstractAggregateRepository;
import com.zijidelu.luframework.starter.scanner.AbstractAutoScanner;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.description.type.TypeDescription;
import org.springframework.core.ResolvableType;
import org.springframework.stereotype.Component;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

/**
 * 聚合转换器扫描器。
 *
 * @author ZIJIDELU
 * @datetime 2025/10/20 22:03
 */
@Component
@RequiredArgsConstructor
@Slf4j
public class AggregateRootConverterScanner extends AbstractAutoScanner {

    @Override
    public Class<? extends AbstractAutoScanner> dependOn() {
        return AggregateConverterScanner.class;
    }

    @Override
    public void start() {
        // 按泛型参数组合去重
        final Set<String> processedTypePairs = new HashSet<>();

        // PDConvert
        StreamUtil.smartStream(getSpringDynamicBeanRegisterUtil().getBeansOfType(AggregateRootConverter.class).values())
                .forEach((bean) -> {
                    final ResolvableType beanResolvableType = ResolvableType.forInstance(bean);
                    final Class<?> beanClass = Objects.requireNonNull(beanResolvableType.resolve());
                    final String packageName = beanClass.getPackageName();
                    // 解析泛型参数
                    final ResolvableType[] resolvableTypes = SpringBeanTypeUtil.resolvableTargetClassTypes(bean, AggregateRootConverter.class);

                    if (resolvableTypes.length < 4) {
                        // 跳过泛型信息不完整的
                        return;
                    }

                    final Class<?> poClass = resolvableTypes[0].resolve();
                    final Class<?> dataModelClass = resolvableTypes[1].resolve();
                    final Class<?> entityClass = resolvableTypes[2].resolve();
                    final Class<?> aggregateRootClass = resolvableTypes[3].resolve();
                    if (poClass == null || dataModelClass == null || entityClass == null || aggregateRootClass == null) {
                        // 跳过无法解析泛型的
                        return;
                    }
                    final String typeKey = Vault.calcItemKeyWithClass(poClass, dataModelClass, entityClass);
                    // 跳过已处理的类型对
                    if (processedTypePairs.contains(typeKey)) {
                        return;
                    }

                    // 注册聚合根仓库
                    aggregateRepositoryScanner(
                            packageName,
                            poClass,
                            dataModelClass,
                            entityClass,
                            aggregateRootClass
                    );

                    // 标记为已处理
                    processedTypePairs.add(typeKey);

                });

    }

    /**
     * 聚合根仓库扫描器。
     *
     * @param packageName        包名
     * @param poClass            实体类
     * @param dataModelClass     数据模型类
     * @param entityClass        实体类
     * @param aggregateRootClass 聚合根类
     * @return 聚合根仓库实例
     */
    private Object aggregateRepositoryScanner(String packageName, Class<?> poClass, Class<?> dataModelClass, Class<?> entityClass, Class<?> aggregateRootClass) {
        // DataRepository
        return genericRegisterBeans(calcUniDomain(dataModelClass, RepositoryConstant.AGGREGATE_REPOSITORY_SUFFIX),
                packageName,
                TypeDescription.Generic.Builder.parameterizedType(AbstractAggregateRepository.class,
                        poClass, dataModelClass, entityClass, aggregateRootClass
                ).build(),
                TypeDescription.Generic.Builder.parameterizedType(AggregateRepository.class,
                        dataModelClass, entityClass, aggregateRootClass
                ).build()
        );
    }

}
